﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel;
using System.Xml.Serialization;
using System.Collections.ObjectModel;

namespace ViewMaker.Core.Controls
{
    /// <summary>
    /// TreeView Viewコントロール
    /// </summary>
    public class TreeViewControl : HeaderViewControl
    {
        public new class Properties : HeaderViewControl.Properties
        {
            public const string ItemsSource = "ItemsSource";
            public const string DisplayMember = "DisplayMember";
            public const string IsSelected = "IsSelected";
            public const string IsExpanded = "IsExpanded";
            public const string SelectedObject = "SelectedObject";
            public const string SelectedItemChangedCommand = "SelectedItemChangedCommand";
        }

        /// <summary>
        /// 一覧用のデータソース
        /// </summary>
        [View(ViewControlType.ComboBox)]
        [ViewProperty(ComboBoxViewControl.Properties.ItemsSource, "TreeViewItemBindableList")]
        [ViewProperty(ComboBoxViewControl.Properties.IsEditable, true)]
        public string ItemsSource { get; set; }

        /// <summary>
        /// ItemsSourceの各アイテムの表示に利用するプロパティのパス
        /// </summary>
        [View(ViewControlType.ComboBox)]
        [ViewProperty(ComboBoxViewControl.Properties.ItemsSource, "TreeViewItemBindableList")]
        [ViewProperty(ComboBoxViewControl.Properties.IsEditable, true)]
        public string DisplayMember { get; set; }

        /// <summary>
        /// ItemsSourceの各アイテムの選択中かを示すプロパティのパス（Wpf）
        /// </summary>
        [View(ViewControlType.ComboBox)]
        [ViewProperty(ComboBoxViewControl.Properties.ItemsSource, "TreeViewItemBindableList")]
        [ViewProperty(ComboBoxViewControl.Properties.IsEditable, true)]
        [ViewProperty(ViewControl.Properties.IsEnabled, "IsWpf")]
        public string IsSelected { get; set; }

        /// <summary>
        /// ItemsSourceの各アイテムを展開するかを示すプロパティのパス（Wpf）
        /// </summary>
        [View(ViewControlType.ComboBox)]
        [ViewProperty(ComboBoxViewControl.Properties.ItemsSource, "TreeViewItemBindableList")]
        [ViewProperty(ComboBoxViewControl.Properties.IsEditable, true)]
        [ViewProperty(ViewControl.Properties.IsEnabled, "IsWpf")]
        public string IsExpanded { get; set; }

        /// <summary>
        /// ItemsSourceの選択中のアイテムを保持するプロパティのパス（Silverlight）
        /// </summary>
        [View(ViewControlType.ComboBox)]
        [ViewProperty(ComboBoxViewControl.Properties.ItemsSource, "BindablePathList")]
        [ViewProperty(ComboBoxViewControl.Properties.IsEditable, true)]
        [ViewProperty(ViewControl.Properties.IsEnabled, "IsSilverlight")]
        public string SelectedObject { get; set; }

        /// <summary>
        /// 選択データ変更時に実行するコマンド
        /// </summary>
        [Display(Name = "SelectedItemChanged", GroupName = CommandGroup)]
        [View(ViewControlType.ComboBox)]
        [ViewProperty(ComboBoxViewControl.Properties.ItemsSource, "Item.CommandList")]
        [ViewProperty(ComboBoxViewControl.Properties.IsEditable, true)]
        public string SelectedItemChangedCommand { get; set; }


        [XmlIgnore]
        [Browsable(false)]
        public ObservableCollection<string> TreeViewItemBindableList
        {
            get
            {
                if (this.Item.BindPath == null) return null;
                return this.Item.CreateChildBindablePath(this.Item.BindPath);
            }
        }

        [XmlIgnore]
        [Browsable(false)]
        public override bool CanOverrideWidth { get { return false; } }

        [XmlIgnore]
        [Browsable(false)]
        public override bool CanOverrideHeight { get { return false; } }

        #region ShouldSerialize

        public override bool ShouldSerializeVerticalAlignment() { return true; }

        #endregion


        public TreeViewControl()
        {
            ControlType = ViewControlType.TreeView;

            HeaderPosition = LayoutHeaderPosition.Hidden;
            StreachAlign();
        }

        public override List<XamlNode> CreateXaml(XamlNode parent)
        {
            var list = base.CreateXaml(parent);
#if !SILVERLIGHT
            var node = parent.CreateElement("TreeView");
            var resources = node.AddElement("TreeView.ItemTemplate");
            var template = resources.AddElement("HierarchicalDataTemplate");
#else
            var node = parent.CreateElement("sdk", "http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk", "TreeView");
            var resources = node.CreateElement("sdk", "http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk", "TreeView.ItemTemplate");
            node.AppendChild(resources);
            var hieraTemp = node.CreateElement("sdk", "http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk", "HierarchicalDataTemplate");
            var template = resources.AppendChild(hieraTemp);
#endif
            SetBindingAttribute(node, "ItemsSource", Item.BindPath, true);
            SetBindingAttribute(template, "ItemsSource", ItemsSource, true);
            if (!string.IsNullOrEmpty(DisplayMember))
            {
                var text = template.AddElement("TextBlock");
                SetBindingAttribute(text, "Text", DisplayMember, true);
            }
#if !SILVERLIGHT
            var styleContainer = node.AddElement("TreeView.ItemContainerStyle");
            var style = styleContainer.AddElement("Style");
            style.SetAttribute("TargetType", "{x:Type TreeViewItem}");
            if (!string.IsNullOrEmpty(IsSelected))
            {
                var selectElement = style.AddElement("Setter");
                selectElement.SetAttribute("Property", "IsSelected");
                selectElement.SetAttribute("Value", "{Binding " + IsSelected + ", Mode=TwoWay}");
            }
            if (!string.IsNullOrEmpty(IsExpanded))
            {
                var expandElement = style.AddElement("Setter");
                expandElement.SetAttribute("Property", "IsExpanded");
                expandElement.SetAttribute("Value", "{Binding " + IsExpanded + ", Mode=TwoWay}");
            }
            var fontSize = GetFontSize();
            if (fontSize.HasValue)
            {
                var setter = style.AddElement("Setter");
                setter.SetAttribute("Property", "FontSize");
                setter.SetAttribute("Value", fontSize.ToString());
            }
            var fore = GetForeground();
            if (!string.IsNullOrEmpty(fore))
            {
                var setter = style.AddElement("Setter");
                setter.SetAttribute("Property", "Foreground");
                setter.SetAttribute("Value", fore);
            }
            var back = GetBackground();
            if (!string.IsNullOrEmpty(back))
            {
                var setter = style.AddElement("Setter");
                setter.SetAttribute("Property", "Background");
                setter.SetAttribute("Value", back);
            }

#else
            if (!string.IsNullOrEmpty(SelectedObject))
            {
                var behaviors = node.CreateElement("i", "http://schemas.microsoft.com/expression/2010/interactivity", "Interaction.Behaviors");
                node.AppendChild(behaviors);

                var behavior = node.ParseElement("<vg:TreeViewItemBehavior vg:SelectedObject=\"{Binding Path=" + SelectedObject + ", Mode=TwoWay}\" "
                     + "xmlns:vg=\"clr-namespace:ViewMaker.Core.Silverlight;assembly=SilverlightViewMaker.Core\" />");
                behaviors.AppendChild(behavior);

            }
#endif
            if (!string.IsNullOrEmpty(SelectedItemChangedCommand)) AddBehavior(node, "TreeViewSelectedItemChangedBehavior", SelectedItemChangedCommand);
            ApplyBaseProperty(node);
            list.Add(node);
            return list;
        }

        protected override void ItemPropertyChanged(PropertyChangedEventArgs e)
        {
            base.ItemPropertyChanged(e);
            if (e.PropertyName == "BindPath")
            {
                OnPropertyChanged("TreeViewItemBindableList");
            }
        }


    }

}
